#ifndef DICCARRAY_H
#define DICCARRAY_H

#include "aed2/Lista.h"
#include "aed2/Arreglo.h"
#include "tupla.h"
#include "auxiliares.h"

#include <iostream>
#include <cassert>

using namespace std;
using namespace aed2;

template<class S>
class diccarray
{

    public:

		diccarray();
        diccarray( Lista<tupla<Cliente, S> >, Nat);

        bool definido(Cliente);
        S& obtener(Cliente);

        diccarray<S>& operator=(const diccarray<S>&);
		bool operator==(const diccarray<S>&) const;
	
    private:

        Arreglo<tupla<Cliente, S> > pDatos;
        int tam;

};

template<class S>
diccarray<S>::diccarray()
{

}



void SelectionSort(int arreglo[], int n)
{
	int pos;
	int aux;

	for (int i=0; i < n-1; i++)
	{
	    pos = i;

		for (int j=i+1; j < n; j++)
		{

		if (arreglo[j] < arreglo[pos])
                   pos=j;

		}

		if (pos != i)
		{
			 aux = arreglo[i];
			 arreglo[i] = arreglo[pos];
			 arreglo[pos] = aux;
		}
	}
}


template<class S>
diccarray<S>::diccarray( Lista<tupla<Cliente, S> > cls, Nat n)
{
    assert(n > 0 && cls.Longitud() == n);

    int arregloAux[n];
    int i = 0;

    Arreglo<tupla<Cliente, S> > aux(n);
    pDatos=aux;

    this->tam = n;

    typename Lista< tupla<Cliente,S> >::Iterador listaClientes = cls.CrearIt();

    while (listaClientes.HaySiguiente()) {

        arregloAux[i] = listaClientes.Siguiente().first ;

        listaClientes.Avanzar();

        i++;
    }


    SelectionSort(arregloAux,n);

    listaClientes = cls.CrearIt();

    i = 0;

    while (i < n) {

        listaClientes = cls.CrearIt();

        while (listaClientes.HaySiguiente()) {

            if (arregloAux[i] == listaClientes.Siguiente().first) {


               pDatos.Definir(i,listaClientes.Siguiente());

                break;
            }

			listaClientes.Avanzar();
		}

        i++;
	}
}

template<class S>
bool diccarray<S>::definido(Cliente c)
{

    assert(this->tam > 0);

    int iMax,iMin,iMid;

    iMin = 0;
    iMax = this->tam-1;

    while (iMax >= iMin) {

		iMid =  (iMin + iMax) / 2;

		if(this->pDatos[iMid].first == c) {

			return true;

		} else if (this->pDatos[iMid].first < c) {

			iMin = iMid + 1;

		} else {

			iMax = iMid - 1;
		}

		}

    return false;

}

template<class S>
S& diccarray<S>::obtener(Cliente c)
{

    assert(this->tam > 0);

    int iMax,iMin,iMid;

    iMin = 0;
    iMax = this->tam-1;

    while (iMax >= iMin) {

      iMid =  (iMin + iMax) / 2;

      if(this->pDatos[iMid].first == c) {

        return this->pDatos[iMid].second;

      } else if (this->pDatos[iMid].first < c) {

        iMin = iMid + 1;

      } else {

        iMax = iMid - 1;
      }

    }

}

template<class S>
diccarray<S>& diccarray<S>::operator=(const diccarray<S>& otro) {

    assert(otro.tam > 0);

    int i = 0;

    this->tam = otro.tam;
    Arreglo<tupla<Cliente, S> > aux(tam);
    pDatos=aux;

    while(i < otro.tam) {

        pDatos.Definir(i,otro.pDatos[i]);

        i++;
    }

    return *this;

}

template<class S>
bool diccarray<S>::operator==(const diccarray<S>& otro) const {
	
	if (this->tam == otro.tam) {

		int i = 0;
		
		while(i < this->tam) {

			if (this->pDatos[i] != otro.pDatos[i]) {return false;}

			i++;
		}
		
		return true;
		
	}
	
	return false;

}

#endif // DICCARRAY_H
